// *****************************************************
// Aitrox Information Technology
// http://www.proxima-ai.com
// Copyright 2021 Aitrox. All rights reserved.
//
// Filename: mqttclient.go
// CreateDate: 2023-06-08
// Author: zjp
// Description: mqtt客户端
// ******************************************************
package mqtt

import (
	"fmt"
	"time"

	MQTT "github.com/eclipse/paho.mqtt.golang"
)

type MqttClient struct {
	Qos      byte
	Retained bool
	ID       string
	Client   MQTT.Client
	//Topics   map[string]mqttInstance.MessageHandler
}

type MqttConnectConfig struct {
	Broker      string //代理服务
	User        string //用户名
	Password    string //登录密码
	Qos         byte   //服务质量 0: 尽力而为，消息可能会丢，但绝对不会重复；1: 消息绝不会丢，但可能会重复传输；2: 恰好一次，每条消息肯定会被传输仅一次
	Retained    bool   //保留信息
	ClientId    string //客户端ID
	WillEnabled bool   //遗愿
	WillTopic   string //遗愿主题
	WillPayload string //遗愿消息
	WillQos     byte   //遗愿服务质量
}

func NewMqttClient(config MqttConnectConfig) *MqttClient {
	var c *MqttClient = &MqttClient{}

	opts := MQTT.NewClientOptions()
	opts.AddBroker(config.Broker)
	opts.SetClientID(config.ClientId)
	opts.SetMaxReconnectInterval(time.Second * 5)
	if config.WillEnabled {
		opts.SetWill(config.WillTopic, config.WillPayload, config.WillQos, config.Retained)
	}

	if config.User != "" {
		opts.SetUsername(config.User).SetPassword(config.Password)
	}

	//初始化连接/断开成功回调
	opts.OnConnect = func(c MQTT.Client) {
		fmt.Println("MQTT 连接成功")
	}
	opts.OnConnectionLost = func(c MQTT.Client, err error) {
		fmt.Println("MQTT 断开连接: ", err)
	}

	c.Qos = config.Qos
	c.Retained = config.Retained
	c.ID = config.ClientId
	c.Client = MQTT.NewClient(opts)

	return c
}

func (c *MqttClient) Connect() error {
	if token := c.Client.Connect(); token.Wait() && token.Error() != nil {
		println("mqtt Conn err:" + token.Error().Error())
		return token.Error()
	}

	return nil
}

func (c *MqttClient) Disconnect() {
	c.Client.Disconnect(250)
}

func (c *MqttClient) ClientPublishMsg(topic, msg string) error {

	token := c.Client.Publish(topic, 0, false, msg)
	if token.Wait() && token.Error() != nil {
		println("mqtt Pub err:" + token.Error().Error())
	}
	return token.Error()
}
